<template>
  <teleport to="body">
    <section
      v-if="keyboardVisible"
      :id="KEYBOARD_DOM_ID"
      class="keyboard-wrapper custom-keyboard-wrapper__safe-area"
    >
      <ul class="bd-input-area">
        <li
          v-for="(line, idx) in areas"
          v-show="type === 'area'"
          :key="idx"
          class="bd-input-line"
        >
          <span
            v-for="(key, i) in line"
            :key="i"
            class="button"
            :class="buttonStub(key)"
            @click="fill(key)"
          >
            {{ key !== 'delete' ? key : '' }}
          </span>
        </li>
        <li
          v-for="(line, index) in nums"
          v-show="type !== 'area'"
          :key="index"
          class="bd-input-line"
        >
          <span
            v-for="(key, i) in line"
            :key="i"
            class="button"
            :class="buttonStub(key)"
            :disabled="!buttonsEnabled(key)"
            @click="fill(key)"
          >
            {{ key !== 'delete' ? key : '' }}
          </span>
        </li>
      </ul>
    </section>
  </teleport>
</template>

<script setup lang="ts">
import {
  computed, ref, onMounted, onBeforeUnmount,
} from 'vue';

import { CAR_NUM_LIST_DOM_ID, KEYBOARD_DOM_ID } from './constants';

const emits = defineEmits(['fill', 'delete']);

const props = defineProps({
  /**
     * 标记本键盘当前输入的类型
     * letter: 仅允许字母输入
     * number: 仅允许字母和数字输入
     * chinese: 允许所有类型的输入
     */
  type: {
    type: String,
    required: true,
  },

  /**
     * @description: 当前键盘输入位置
     */
  focusIndex: {
    type: Number,
    required: true,
  },
});

const keyboardVisible = ref(false);
const areas = ref([
  ['京', '津', '沪', '渝', '冀', '豫', '云', '辽', '黑', '湘'],
  ['皖', '鲁', '新', '苏', '浙', '赣', '鄂', '桂', '甘', '晋'],
  ['蒙', '陕', '吉', '闽', '贵', '粤', '青', '藏', '川', '宁'],
  ['琼', '临', '使', '港', '澳', '台', '学', '虚', 'W', 'delete']
]);

const nums = computed(() => (props.focusIndex === 6 || props.focusIndex === 7
  ? [
    ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
    ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'P', '学', '领'],
    ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '警'],
    ['Z', 'X', 'C', 'V', 'B', 'N', 'M', '港', '澳', 'delete']
  ]
  : [
    ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
    ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'O', 'P', '领'],
    ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '警'],
    ['Z', 'X', 'C', 'V', 'B', 'N', 'M', '港', '澳', 'delete']
  ]));

const buttonsEnabled = (key:string) => {
  const isNums = /[0-9]/;
  const isLetters = /[A-Z]/;
  const filterO = /[^O]/;

  if (key === 'delete' || props.type === 'area') {
    return true;
  }
  if (props.type === 'letter') {
    return isLetters.test(key);
  }
  if (props.type === 'number') {
    return (isNums.test(key) || isLetters.test(key)) && filterO.test(key);
  }
  return props.type === 'chinese' && filterO.test(key);
};

const buttonStub = (key:string) => ({
  stub: key.toString().length < 1,
  disabled: !buttonsEnabled(key),
  'bd-delete': key === 'delete',
});

const fill = (val:string) => {
  if (buttonsEnabled(val)) {
    // emits('fill', val === 'delete' ? '' : val);
    if (val === 'delete') {
      emits('delete', '');
    } else {
      emits('fill', val);
    }
  }
};

const handleOpen = () => {
  keyboardVisible.value = true;
};

const handleClose = () => {
  keyboardVisible.value = false;
};

const handleClickOutside = (event: MouseEvent) => {
  const numberOfKeys = document.getElementById(CAR_NUM_LIST_DOM_ID);
  const keyboardElement = document.getElementById(KEYBOARD_DOM_ID);
  if (!numberOfKeys?.contains(event.target as Node) && !keyboardElement?.contains(event.target as Node)) {
    handleClose();
  }
};

onMounted(() => {
  window.addEventListener('click', handleClickOutside);
  window.addEventListener('touchstart', handleClickOutside as any, { passive: false });
});

onBeforeUnmount(() => {
  window.removeEventListener('click', handleClickOutside);
  window.removeEventListener('touchstart', handleClickOutside as any);
});

defineExpose({
  handleClose,
  handleOpen,
});
</script>

<style lang="scss" scoped>
.keyboard-wrapper {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 999;
  font-size: 14px;
  background-color: #e5e5e5;
  box-shadow: 0 -1px 5px 0 rgb(0 0 0 / 7%);

  .bd-input-area {
    position: relative;
    padding: 6px 2px 12px;
  }

  .bd-input-line {
    display: flex;

    + .bd-input-line {
      margin-top: 0.6em;
    }

    > .button {
      flex: 1;
      margin: 0 0.7%;
      overflow: hidden;
      font-size: 16px;
      line-height: 45px;
      color: #030303;
      text-align: center;
      background-color: #fff;
      border-radius: 4px;

      &.disabled {
        color: #8f8f8f;
        background-color: #f4f4f4;
      }

      &.stub {
        visibility: hidden;
        opacity: 0;
      }
    }
  }

  .bd-delete {
    flex: 2;
    height: 3em;
    text-align: center;
    background: #fff url('../../assets/images/clear.png') no-repeat center;
    background-size: auto 1em;
    border-radius: 4px;
  }
}
</style>
